﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Web.Caching;

namespace Univar
{
	/// <summary>
	/// An implementation of the DynamicStore<T> class that provides the NullableValue property for non nullable types.
	/// It returns null if the key does not exist.
	/// </summary>
	/// <typeparam key="T">The generic type T for the variable. 
	/// Note that only non nullable types are accepted</typeparam>
	public class NullableDynamicStore<T> : DynamicStore<T> where T : struct
	{
		public NullableDynamicStore(string key, params Sources[] sourceTypes)
			: base(default(T), key, null, null, null, null, sourceTypes) { }
		public NullableDynamicStore(string key, int? targetTypes, params Sources[] sourceTypes)
			: base(default(T), key, null, null, null, targetTypes, sourceTypes) { }
		public NullableDynamicStore(T defaultValue, string key, params Sources[] sourceTypes)
			: base(defaultValue, key, null, null, null, null, sourceTypes) { }
		public NullableDynamicStore(T defaultValue, string key, int? targetTypes, params Sources[] sourceTypes)
			: base(defaultValue, key, null, null, null, targetTypes, sourceTypes) { }

		/// <summary>
		/// Initializes a new instance of the <see cref="NullableDynamicStore&lt;T&gt;"/> class.
		/// </summary>
		/// <param name="defaultValue">The default value used when the specified key does not exist in the 
		/// specified sources.</param>
		/// <param name="key">The key for the stored value.</param>
		/// <param name="cookieLifeTime">
		/// The cookie life time. Its value is set to 100 days when a null value is specified.</param>
		/// <param name="cacheLifeTime">
		/// The cache life time. Its value is set to 20 minutes when a null value is specified.</param>
		/// <param name="targetTypes">Specifies the storage types where the value is allowed to be saved. 
		/// Those are hardcoded in the Targets class. Several types can be specified
		/// by adding them up using the '+' operator as such: 
		/// Targets.Cookie + Targets.Session + Targets.Cache</param>
		/// <param name="sourceTypes">A list of storage types from which the value will be retrieved
		/// Each type is hardcoded within the Sources enum and they must be seperated by a comma.
		/// The order in which they are listed determines the order in which they are accessed until a value is found.
		/// </param>
		public NullableDynamicStore(T defaultValue, string key, TimeSpan? cookieLifeTime, CacheDependency cacheDependency, TimeSpan? cacheLifeTime,
			int? targetTypeFlags, params Sources[] sourceTypes)
			: base(defaultValue, key, cookieLifeTime, cacheDependency, cacheLifeTime, targetTypeFlags, sourceTypes) { }

		public T? NullableValue
		{
			get
			{
				Sources source = Sources.None;
				T value = GetValue<T>(_key, out source, _sourceStorages);
				if (source != Sources.None)
					return value;
				else
					return null;
			}
			set
			{
				if (value.HasValue)
					SetValue(_key, value.Value);
				else
					ClearTargetsOnly();
			}
		}
	}
}